#include <all_gd.h>
#pragma hdrstop
//#pragma package(smart_init)

#include "int.h"

#if 0
  #define  PROC( v )
  #define  Log( v )
#else
  #define  PROC( v )  INProc __proc v ;
  #define  Log( v )   INProc::Say v
#endif

struct {
  CONSTSTR nm;
  int      v;
} StdZooms[] = {
  { "5",    5 },
  { "10",   10 },
  { "25",   25 },
  { "50",   50 },
  { "75",   75 },
  { "100",  100 },
  { "150",  150 },
  { "200",  200 },
  { "300",  300 },
  { "400",  400 },
  { "800",  800 },
  { "1000", 1000 },

  { _L("Fit width"),   ZOOM_WIDTH },
  { _L("Fit height"),  ZOOM_HEIGHT },
  { _L("Fit all map"), ZOOM_FULL },
  { 0,0 }
};

//---------------------------------------------------------------------------
// ModuleOZISource
//---------------------------------------------------------------------------
ModuleOZISource::ModuleOZISource( PMVModule o )
    : MVFilesMapSource( o )
  {
    Pattern = "*.map";
}

bool ModuleOZISource::LoadMap( PMVMapInfo mi )
  {
 return Plugin->Data->LoadMapIntf( mi->File.c_str() );
}

void ModuleOZISource::RefreshMapList( MVMapEnumEvent cb, LPVOID Ptr )
  {  CONSTSTR dirs = GOPT( "MapDirs","" );
     int      cn = StrColCount( dirs, "\n" );

     for( int n = 1; n <= cn; n++ ) {
       char *m,
             path[ MAX_PATH_SIZE ];
       TStrCpy( path, StrGetCol(dirs, n, "\n" ) );
       m = strchr( path, '\r' ); if ( m ) *m = 0;
       for( m = path; *m && isspace(*m); m++ );
       if ( !m[0] || m[0] == '#' || m[0] == ';' )
         continue;

       ScanDirs( m, cb, Ptr );
     }
}
//---------------------------------------------------------------------------
// ModuleOZILoader
//---------------------------------------------------------------------------
ModuleOZILoader::ModuleOZILoader( PMVModule o )
   : OZIMapLoader( o )
  {
    LoaderName = OZI_LOADER_NAME;
}

PMVMapLoader ModuleOZILoader::CreateClone( void )       { return new ModuleOZILoader( Plugin ); }
bool         ModuleOZILoader::FullLoad( CONSTSTR fnm )  { return Plugin->Data->LoadMapIntf( fnm ); }

//---------------------------------------------------------------------------
// MapInterface
//---------------------------------------------------------------------------
MapInterface::MapInterface( PModuleOZILoader l, PGFLBitmap b )
    : Loader( l )
  {
     Bitmap = b;
     Proxy  = new MVBitmapProxy( Bitmap );
     Owner  = Plugin;

  //Correct map bounds
     Loader->Raster2GPoint( 0, 0,                              Loader->MapBounds.tl );
     Loader->Raster2GPoint( Bitmap->Width(), 0,                Loader->MapBounds.tr );
     Loader->Raster2GPoint( Bitmap->Width(), Bitmap->Height(), Loader->MapBounds.br );
     Loader->Raster2GPoint( 0, Bitmap->Height(),               Loader->MapBounds.bl );

  //Data
     DrawRect.Set(0,0,0,0);
     Center.Set(0,0);

  //Force create data
     MyRect r;
     Paint( NULL, r );
}

void GV_DECLSPEC MapInterface::Close( void )
  {
     Loader->Clear();
     delete Loader; Loader = NULL;
     delete Proxy;  Proxy = NULL;
     delete Bitmap; Bitmap = NULL;
}

void GV_DECLSPEC MapInterface::GetMapCaption( AnsiString& str )
  {
     if ( Loader )
       str.printf( "%s (%s)",
                   Loader->Caption.c_str(),
                   Loader->ImageFile.c_str() );
}

bool GV_DECLSPEC MapInterface::ContainsPoint( const GPoint& p )
  {
 return Loader ? Loader->Bounds.Contains( p ) : false;
}

//---------------------------------------------------------------------------
// Zooms
//---------------------------------------------------------------------------
void GV_DECLSPEC MapInterface::FillZoomLevels( TStrings *Strings, int& defz )
  {
     Strings->Clear();

     for( int n = 0; StdZooms[n].nm; n++ )
       Strings->AddObject( isdigit(StdZooms[n].nm[0]) ? StdZooms[n].nm : LNG(StdZooms[n].nm),
                           (TObject*)StdZooms[n].v );
     defz = 100;
}

int GV_DECLSPEC MapInterface::ValidateZoom( int v )
  {
    if ( v == ZOOM_WIDTH ||
         v == ZOOM_HEIGHT ||
         v == ZOOM_FULL )
      return v;
 return Max( MIN_ZOOM_PC, Min( v, MAX_ZOOM_PC ) );
}

int GV_DECLSPEC MapInterface::GetZoomLevel( const AnsiString& s )
  {
     for( int n = 0; StdZooms[n].nm; n++ )
       if ( s == StdZooms[n].nm ||
            s == LNG(StdZooms[n].nm) )
         return StdZooms[n].v;
 return atoi( s.c_str() );
}

int GV_DECLSPEC MapInterface::IncZoom( int z ) { if ( z < 100 ) return Min( z+GOPT("SmallZoom",10), 100 ); else return z+GOPT("BigZoom",25); }
int GV_DECLSPEC MapInterface::DecZoom( int z ) { if ( z > 100 ) return Max( z-GOPT("BigZoom",25), 100 ); else return z-GOPT("SmallZoom",10); }

void GV_DECLSPEC MapInterface::ZoomChanged( int z )
  {
     switch( z ) {
       case  ZOOM_WIDTH: Proxy->SetRatio( bmrWidth, 0 ); break;
       case ZOOM_HEIGHT: Proxy->SetRatio( bmrHeight, 0 ); break;
       case   ZOOM_FULL: Proxy->SetRatio( bmrFit, 0 ); break;
                default: Proxy->SetRatio( bmrFree, z );
     }
}

//---------------------------------------------------------------------------
// Scrolls
//---------------------------------------------------------------------------
void GV_DECLSPEC MapInterface::ScrollTo( int x, int y )
  {
     Proxy->SetOffsets( x, y );
}

void GV_DECLSPEC MapInterface::ScrollToViewPoint( int x, int y, ScrenScrollTypes type )
  {  int ox, oy;

     x += Proxy->OffX;
     y += Proxy->OffY;

     switch( type ) {
       case sstScreenCenter:
                    default: ox = x - Info.ScreenW() / 2;
                             oy = y - Info.ScreenH() / 2;
     }
     Proxy->SetOffsets( ox, oy );
}

//---------------------------------------------------------------------------
// Coords <->
//---------------------------------------------------------------------------
void GV_DECLSPEC MapInterface::Screen2G( int x, int y, GPoint& gp )
  {
     if ( Loader ) {
       x = Proxy->Screen2Raster( x + Proxy->OffX );
       y = Proxy->Screen2Raster( y + Proxy->OffY );
       Loader->Raster2GPoint( x, y, gp );
     }
}

void GV_DECLSPEC MapInterface::G2Screen( GCoord_t x, GCoord_t y, MyPoint& sp )
  {
     if ( Loader ) {
       Loader->G2RasterPoint( x, y, sp );
       sp.x = Proxy->Raster2Screen( sp.x ) - Proxy->OffX;
       sp.y = Proxy->Raster2Screen( sp.y ) - Proxy->OffY;
     }
}

//---------------------------------------------------------------------------
// Paint
//---------------------------------------------------------------------------
void GV_DECLSPEC MapInterface::Paint( TCanvas *dc, MyRect& dr )
  {
     if ( DrawRect.Width() != Info.ScreenW() ||
          DrawRect.Height() != Info.ScreenH() ) {
       DrawRect.x1 = Info.ScreenW();
       DrawRect.y1 = Info.ScreenH();

       Proxy->SetOutputArea( DrawRect );
     }

     if ( Proxy->Ratio == -1 )
       Proxy->SetRatio( bmrFree, Info.Zoom(-1) == -1 ? 100 : Info.Zoom(-1) );

     if ( dc )
       Proxy->Paint( dc->Handle, DrawRect, dr);
}

//---------------------------------------------------------------------------
// Preview
//---------------------------------------------------------------------------
void GV_DECLSPEC MapInterface::idPreviewScrollTo( int w, int h, int offx, int offy )
  {
     offx = Max( 0, Min( offx, w ) );
     offy = Max( 0, Min( offy, h ) );

     offx = Proxy->Raster2Screen( Bitmap->Width() ) * offx / w - Info.ScreenW()/2;
     offy = Proxy->Raster2Screen( Bitmap->Height() ) * offy / h - Info.ScreenH()/2;
     Proxy->SetOffsets( offx, offy );
}

void GV_DECLSPEC MapInterface::idPreviewGetCurrentPositionRect( const MyRect& c, MyRect& r )
  {  int w = Proxy->Raster2Screen( Bitmap->Width() ),
         h = Proxy->Raster2Screen( Bitmap->Height() );
     int v;

     v = Proxy->OffX;
     r.x = c.x + c.Width() * v / w;

     v = Min( Info.ScreenW(), w - Proxy->OffX );
     r.x1 = r.x + c.Width() * v / w;

     v = Proxy->OffY;
     r.y = c.y + c.Height() * v / h;

     v = Min( Info.ScreenH(), h - Proxy->OffY );
     r.y1 = r.y + c.Height() * v / h;
}

bool GV_DECLSPEC MapInterface::GetPreviewInfo( PMVRasterInfo p )
  {
     memset( p, 0, sizeof(*p) );

     p->Flags        = MVRF_HAS_FULLBITMAP | MVRF_HAS_BITS;
     p->Width        = Bitmap->Width();
     p->Height       = Bitmap->Height();
     p->BitmapInfo   = &Proxy->bmI;
     p->Bits         = Proxy->Bits();
     p->GetCurrentPositionRect = idPreviewGetCurrentPositionRect;
     p->ScrollTo               = idPreviewScrollTo;

 return true;
}
